package com.lagou.edu.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * 定义全局过滤器，实现对所有路由进行ip检测，拦截在黑白名单库中的ip
 * @author renpeiqian
 * @date 2021/7/16 11:17
 * @since
 */
@Component //注入容器，才能生效
@Slf4j
public class BlackFilter  implements GlobalFilter , Ordered {

    //模拟黑名单库
    private static List<String> blackList = new ArrayList<>();

    //模拟入库,在类加载时执行。
    static {
        log.info("模拟加载黑白名单库");
        blackList.add("0:0:0:0:0:0:0:1"); //模拟本机地址
    }


    /**
     * @Description
     * 过滤器核心方法 : 获取请求IP，如果在黑名单库，就拦截。否则就放行
     * exchange ：封装了http请求中的 request、response对象的上下文
     * chain :网关过滤器链（include GatewayFilter、GlobalFilter）
     * @Param [exchange, chain]
     * @return reactor.core.publisher.Mono<java.lang.Void>
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //从上下文中获取request、response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //获取客户端ip
        String clientIp = request.getRemoteAddress().getHostString();
        log.info("拦截到访问ip：【{}】",clientIp);

        //查询请求是否为黑名单库中ip
        if (blackList.contains(clientIp)){
            //拦截
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            log.debug("【拦截违法请求：{}】",clientIp);
            String data = "Request be denied!";
            DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());
            return response.writeWith(Mono.just(wrap));
        }

        //正常访问，放行
        return chain.filter(exchange);
    }

    /**
     * @Description :标识该过滤器的优先级 。数值越小，优先级越高
     * @Param []
     * @return int
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
